﻿#region Copyright 
/*-------------------------------------------------------------------------
* 命名空间名称/文件名:    SSPivot.Common.Helpers.Http/Class1 
* CLR版本:     4.0.30319.42000
* 机器名称:    DESKTOP-NHMLO8A
* 功 能：       N/A
* 类 名：       Class1
* 创建时间：  2025/5/21 18:47:53
* 版本号：      v1.0
* 创建人:        xulong
*-------------------------------------------------------------------------*/
#endregion
using Microsoft.Extensions.DependencyInjection;
using Polly.Extensions.Http;
using Polly.Timeout;
using Polly;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SSPivot.Common.Helpers.Http;

namespace Microsoft.Extensions.DependencyInjection
{
    /// <summary>
    /// httpclient 扩展
    /// </summary>
    public static class HttpClientExtensions
    {
        /// <summary>
        /// addservice
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configure"></param>
        /// <returns></returns>
        public static IServiceCollection AddHttpClientService(this IServiceCollection services,
            Action<Dictionary<string, HttpClientConfig>> configure = null)
        {
            services.AddOptions<Dictionary<string, HttpClientConfig>>()
                .Configure(options => configure?.Invoke(options));

            services.AddHttpClient();
            services.AddSingleton<IHttpClientService, HttpClientService>();

            services.AddHttpClient("default", client => { });

            if (configure != null)
            {
                var configs = new Dictionary<string, HttpClientConfig>();
                configure(configs);

                foreach (var (name, config) in configs)
                {
                    services.AddHttpClient(name)
                        .ConfigureHttpClient(client =>
                        {
                            client.BaseAddress = new Uri(config.BaseAddress);
                            client.Timeout = config.Timeout;
                            foreach (var header in config.DefaultHeaders)
                            {
                                client.DefaultRequestHeaders.TryAddWithoutValidation(header.Key, header.Value);
                            }
                        })
                        .AddPolicyHandler((serviceProvider, request) =>
                            CreatePolicy(config));
                }
            }

            return services;
        }

        private static IAsyncPolicy<HttpResponseMessage> CreatePolicy(HttpClientConfig config)
        {
            var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(
                config.Timeout, TimeoutStrategy.Optimistic);

            var retryPolicy = HttpPolicyExtensions
                .HandleTransientHttpError()
                .OrResult(r => !r.IsSuccessStatusCode)
                .WaitAndRetryAsync(config.RetryCount, _ => TimeSpan.FromMilliseconds(500));

            return Policy.WrapAsync(retryPolicy, timeoutPolicy);
        }


        #region decmo

        //        使用示例（Program.cs）：

        //csharp
        //var builder = WebApplication.CreateBuilder(args);

        //builder.Services.AddHttpClientService(config =>
        //{
        //    config["WeatherApi"] = new HttpClientConfig
        //    {
        //        BaseAddress = "https://api.weather.com",
        //        Timeout = TimeSpan.FromSeconds(20),
        //        RetryCount = 3,
        //        DefaultHeaders = new Dictionary<string, string>
        //        {
        //            ["Accept"] = "application/json",
        //            ["User-Agent"] = "MyApp/1.0"
        //        }
        //};
        //});

        //// 或者使用静态管理器
        //HttpClientManager.Initialize(services =>
        //{
        //    services.AddHttpClientService(config =>
        //    {
        //        config["PaymentApi"] = new HttpClientConfig
        //        {
        //            BaseAddress = "https://api.payment.com",
        //            RetryCount = 5
        //        };
        //    });
        //});



        //        典型调用示例：

        //csharp
        //var response = await HttpClientManager.PostAsync<WeatherData>("WeatherApi", "/forecast",
        //    new Dictionary<string, string>
        //    {
        //        ["latitude"] = "51.5074",
        //        ["longitude"] = "0.1278",
        //        ["units"] = "metric"
        //    },
        //    new RequestOptions
        //    {
        //        Headers = new Dictionary<string, string>
        //        {
        //            ["X-Correlation-ID"] = Guid.NewGuid().ToString()
        //        },
        //        Timeout = TimeSpan.FromSeconds(15),
        //        RetryCount = 2
        //    });

        //if (response.IsSuccess)
        //{
        //    Console.WriteLine($"Current temp: {response.Data.Temperature}°C");
        //}
        //else
        //{
        //    Console.WriteLine($"Request failed: {response.StatusCode} - {response.ErrorMessage}");
        //}
        #endregion
    }
}
